package com.tools.scanner.utils

import android.graphics.Bitmap
import android.graphics.Color
import com.google.android.gms.tasks.Task
import com.google.mlkit.vision.barcode.BarcodeScanning
import com.google.mlkit.vision.barcode.common.Barcode
import com.google.mlkit.vision.common.InputImage
import com.google.zxing.BarcodeFormat
import com.google.zxing.EncodeHintType
import com.google.zxing.Writer
import com.google.zxing.WriterException
import com.google.zxing.aztec.AztecWriter
import com.google.zxing.common.BitMatrix
import com.google.zxing.datamatrix.DataMatrixWriter
import com.google.zxing.oned.CodaBarWriter
import com.google.zxing.oned.Code128Writer
import com.google.zxing.oned.Code39Writer
import com.google.zxing.oned.Code93Writer
import com.google.zxing.oned.EAN13Writer
import com.google.zxing.oned.EAN8Writer
import com.google.zxing.oned.ITFWriter
import com.google.zxing.oned.UPCAWriter
import com.google.zxing.oned.UPCEWriter
import com.google.zxing.pdf417.PDF417Writer
import com.google.zxing.qrcode.QRCodeWriter
import com.tools.scanner.bean.BarcodeSchema
import java.util.Hashtable

class QrCodeUtil {

    companion object {
        private val mBarcodeScanner = BarcodeScanning.getClient()

        fun processBitmap(image: InputImage): Task<List<Barcode>> {
            return mBarcodeScanner.process(image)
        }

        fun createQrCode(
            content: String,
            barcodeSchema: BarcodeSchema,
            width: Int = 300,
            height: Int = 300
        ): Bitmap? {
            try {
                val params = getCodeParams(barcodeSchema)

                val hints = Hashtable<EncodeHintType, Any>()
                hints[EncodeHintType.CHARACTER_SET] = "UTF-8"

                val bitMatrix: BitMatrix =
                    params.first.encode(content, params.second, width, height, hints)

                val bitmap = createBitmap(bitMatrix, Color.BLACK, Color.WHITE)

                return bitmap
            } catch (e: WriterException) {
                e.printStackTrace()
                return null
            }
        }

        private fun createBitmap(matrix: BitMatrix, codeColor: Int, backgroundColor: Int): Bitmap {
            val width = matrix.width
            val height = matrix.height
            val pixels = IntArray(width * height)
            for (y in 0 until height) {
                val offset = y * width
                for (x in 0 until width) {
                    pixels[offset + x] = if (matrix[x, y]) codeColor else backgroundColor
                }
            }
            return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888).apply {
                setPixels(pixels, 0, width, 0, 0, width, height)
            }
        }

        fun getCodeParams(scheme: BarcodeSchema): Pair<Writer, BarcodeFormat> {
            when (scheme) {
                BarcodeSchema.URL,
                BarcodeSchema.TEXT,
                BarcodeSchema.CONTACT,
                BarcodeSchema.EMAIL,
                BarcodeSchema.SMS,
                BarcodeSchema.GEO,
                BarcodeSchema.PHONE,
                BarcodeSchema.CALENDER,
                BarcodeSchema.WIFI -> {
                    return Pair(QRCodeWriter(), BarcodeFormat.QR_CODE)
                }

                BarcodeSchema.EAN_8 -> {
                    return Pair(EAN8Writer(), BarcodeFormat.EAN_8)
                }

                BarcodeSchema.EAN_13 -> {
                    return Pair(EAN13Writer(), BarcodeFormat.EAN_13)
                }

                BarcodeSchema.UPC_E -> {
                    return Pair(UPCEWriter(), BarcodeFormat.UPC_E)
                }

                BarcodeSchema.UPC_A -> {
                    return Pair(UPCAWriter(), BarcodeFormat.UPC_A)
                }

                BarcodeSchema.CODE_39 -> {
                    return Pair(Code39Writer(), BarcodeFormat.CODE_39)
                }

                BarcodeSchema.CODE_93 -> {
                    return Pair(Code93Writer(), BarcodeFormat.CODE_93)
                }

                BarcodeSchema.CODE_128 -> {
                    return Pair(Code128Writer(), BarcodeFormat.CODE_128)
                }

                BarcodeSchema.ITF -> {
                    return Pair(ITFWriter(), BarcodeFormat.ITF)
                }

                BarcodeSchema.PDF_417 -> {
                    return Pair(PDF417Writer(), BarcodeFormat.PDF_417)
                }

                BarcodeSchema.CODABAR -> {
                    return Pair(CodaBarWriter(), BarcodeFormat.CODABAR)
                }

                BarcodeSchema.DATA_MATRIX -> {
                    return Pair(DataMatrixWriter(), BarcodeFormat.DATA_MATRIX)
                }

                BarcodeSchema.AZTEC -> {
                    return Pair(AztecWriter(), BarcodeFormat.AZTEC)
                }

            }

        }

    }

}